package com.zkq.graduate.controller;

import com.alibaba.fastjson.JSON;
import com.zkq.graduate.enums.DateTimeFormatterEnum;
import com.zkq.graduate.pojo.Role;
import com.zkq.graduate.pojo.Users;
import com.zkq.graduate.service.MqService;
import com.zkq.graduate.service.UserAndRoleService;
import com.zkq.graduate.service.UserService;
import com.zkq.graduate.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.zkq.graduate.enums.ResponseEnum.*;

/**
 * @Author zhangkaiqiang
 * @Date 2019/11/30  21:23
 * @Description TODO
 */

@Slf4j
@RestController
@RequestMapping("/api/v1/user")
@Api(tags = {"用户模块"},description = "包含用户登录、退出接口,以及获取用户信息等接口")
public class UserController {


	@Resource(name = "userService")
	private UserService userService;

	@Resource
	private RedisTemplate redisTemplate;

	@Resource(name = "userAndRoleService")
	private UserAndRoleService userAndRoleService;


	@Resource(name = "mqService")
	private MqService mqService;

	@RequestMapping("/getUserInfo")
	@ApiIgnore
	@ApiOperation(value = "得到用户的信息,包含用户名与角色信息")
	public ResultHandler<Users> getUserInfo(HttpServletRequest request){
		Users users=Users.builder()
				.account((String) request.getAttribute("account"))
				.role((List<Role>) request.getAttribute("role"))
				.build();
		return ResultHandler.success(users);
	}


	@GetMapping("/user")
	@ApiOperation(value = "得到用户的信息,包含用户名和系统菜单权限信息")
	public ResultHandler<Users> getUserPermission(HttpServletRequest request){
		String account=(String) request.getAttribute("account");
		Users user=Users.builder().account(account).build();
		Optional<Users> users=Optional.empty();
		if(StringUtils.isNotBlank(account)){
			 users=userService.findUserByAccount(user);
		}
		user.setUserName(users.map(Users::getUserName).orElse(""));
		user.setPermissions(userService.getUserSystemPermission(request));
		return ResultHandler.success(user);
	}


	@PostMapping("/login")
	@ApiOperation(value = "用户登录操作",notes = "该请求方法包含使用用户名密码登录和短信验证码登录")
	public ResultHandler<String> login(Users user,HttpServletResponse response){
		Map<String,Object> map=new HashMap<>(16);
		// 使用账号密码进行登录
		if(user!=null&&user.getPassword()!=null&&user.getAccount()!=null){
			Optional<Users> users=userService.findUserByAccount(user);
			if(!users.isPresent()){
				return ResultHandler.fail(USER_NOT_EXIST);
			}
			users.ifPresent((item)->{
				// 对用户密码进行MD5加密后进行密码的比对
				String md5Password= MD5Util.mD5Encode(user.getPassword());
				if(Objects.equals(md5Password,item.getPassword())){
					// 校验通过生成token，通过cookie保存到客户端
					item.setRole(userAndRoleService.findRoleByUser(users.get()));
					createToken(item,response);
				}
			});
			return ResultHandler.success();
		}else if(user!=null&&user.getPhone()!=null&&user.getCaptcha()!=null){
			// 使用短信验证码进行登录
			Optional<Users> users=userService.findUserByPhone(user);
			if(users.isPresent()){
				Integer captcha= (Integer) redisTemplate.opsForHash().get(user.getPhone(),"captcha");
				if(Objects.equals(captcha,user.getCaptcha())){
					// 校验通过生成token，通过cookie保存到客户端
					users.get().setRole(userAndRoleService.findRoleByUser(users.get()));
					createToken(users.get(),response);
					return ResultHandler.success();
				}
				return ResultHandler.fail(CAPTCHA_ERROR);
			}
			return ResultHandler.fail(USER_NOT_EXIST);
		}
		return ResultHandler.fail(PARAM_BANK);
	}


	@PostMapping("/message")
	@ApiOperation(value = "用户登录时发送短信验证码",notes = "该请求会使用MQ进行异步短信发送")
	public ResultHandler<String> sendMessage(@RequestParam(value = "phone") String phone){
		if(org.apache.commons.lang3.StringUtils.isNotBlank(phone)){
			// 生成验证码
			int captcha= SendMessageUtil.makeRandomNumber();
			Map<String,Object> map=new HashMap<>();
			map.put("phone",phone);
			map.put("captcha",captcha);
			// 向mq中发送消息
			String message= JSON.toJSONString(map);
			mqService.publish(message);
			// 把验证码保存到redis
			map.put("sendTime", LocalDateTimeUtil.formatLocalDateTime(LocalDateTime.now(), DateTimeFormatterEnum.DEFAULT));
			redisTemplate.opsForHash().putAll(phone,map);
			redisTemplate.expire(phone,2, TimeUnit.MINUTES);
			return ResultHandler.success();
		}
		return ResultHandler.fail(PHONE_NOT_EXIST);
	}


	/**
	 * 生成token并向前端保存token
	 * @param users
	 * @param response
	 */
	@ApiIgnore
	private static void createToken(Users users,HttpServletResponse response){
		// 设置token的过期时间,不建议设计token长时间有效,可以结合redis来刷新token
		final int time=2*60*60*1000;
		Map<String,Object> map=new HashMap<>();
		map.put("id",users.getId());
		map.put("account",users.getAccount());
		map.put("role",users.getRole());
		String token= JwtUtil.createJWT(map,Long.valueOf(time));
		CookieAndSessionUtil.addCookie("token",token,response,time);
	}

}
